package ru.spbu.math.android.cbrf.view;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.RemoteViews;
import ru.spbu.math.android.cbrf.R;
import ru.spbu.math.android.cbrf.charts.ChartsActivity;
import ru.spbu.math.android.cbrf.dataprovider.ProviderManager;
import ru.spbu.math.android.cbrf.model.Rate;
import ru.spbu.math.android.cbrf.model.RateType;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class WidgetProvider extends AppWidgetProvider {

	private static final String LOG_TAG = "RateTypeWidget";

	public static final String UPDATE_CONTENT_ACTION = "WRITE";
	public static final String GET_UPDATES_ACTION = "GET_UPDATES";

	public static final String RATE_TYPE_ID = "RateType ID";

	private static final String Err = "Error";

	private static final String PREFS_NAME = "ru.spbu.math.android.cbrf.view.AppWidgetProvider";
	private static final String PREF_PREFIX_KEY = "prefix_";

	private static List<WidgetContainer> widgetContainers = new ArrayList<WidgetContainer>();

	/*
	 * registering our widget with ID and appropriate RateType.
	 */
	public static void registerWidget(Context context, int widgetId,
			String rateTypeId) {

		Log.d(LOG_TAG, "Registering widget with ID: " + widgetId
				+ "; for RateType: " + rateTypeId);

		WidgetContainer container = findWidgetById(widgetId);
		if (container == null) {
			// in case that we have not this widget in list
			container = new WidgetContainer(widgetId);
			RemoteViews views = new RemoteViews(context.getPackageName(),
					R.layout.widget);
			container.remoteViews = views;
			widgetContainers.add(container);
		}
		container.rateTypeId = rateTypeId;

		// showing
		updateWidget(context, container);

		// calling DataProvider for a first values on a widget
		updateWidgetWithProvider(context, container);
		updateWidget(context, container); // showing
	}

	/*
	 * if it a first start of our widget we most reload all saved preferences
	 * and start the Service.
	 */
	@Override
	public void onEnabled(Context context) {
		super.onEnabled(context);
	}

	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {

		// setting initial views or updating widgets per 10-seconds
		for (int widgetId : appWidgetIds) {

			WidgetContainer container = findWidgetById(widgetId);

			SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME,
					0);
			Log.d(LOG_TAG,
					"prefs.itemId = "
							+ prefs.getString(PREF_PREFIX_KEY + widgetId, null));
			if (prefs.contains(PREF_PREFIX_KEY + widgetId)) {
				Log.d(LOG_TAG, "widget was saved with id : " + widgetId);
				container = new WidgetContainer(widgetId);
				RemoteViews views = new RemoteViews(context.getPackageName(),
						R.layout.widget);
				container.remoteViews = views;
				container.rateTypeId = prefs.getString(PREF_PREFIX_KEY
						+ widgetId, null);
				Log.d(LOG_TAG, "container.rateTapeId : " + container.rateTypeId);
				widgetContainers.add(container);

				updateWidget(context, container);

				updateWidgetWithProvider(context, container);
				appWidgetManager.updateAppWidget(widgetId,
						container.remoteViews);
			} else {

				if (container == null) {
					// in case that we have not this widget in list
					container = new WidgetContainer(widgetId);
					RemoteViews views = new RemoteViews(
							context.getPackageName(), R.layout.widget);
					container.remoteViews = views;
					widgetContainers.add(container);

					appWidgetManager.updateAppWidget(widgetId, views); // showing
				} else {
					// in case that we already have that widget

					updateWidgetWithProvider(context, container);
					appWidgetManager.updateAppWidget(widgetId,
							container.remoteViews); // showing

				}
			}
		}
	}

	@Override
	public void onReceive(Context context, Intent intent) {
		final String action = intent.getAction();
		if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
			final int appWidgetId = intent.getIntExtra(
					AppWidgetManager.EXTRA_APPWIDGET_ID,
					AppWidgetManager.INVALID_APPWIDGET_ID);
			if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
				this.onDeleted(context, new int[] { appWidgetId });
			}
		} else {
			super.onReceive(context, intent);
		}
	}

	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		super.onDeleted(context, appWidgetIds);

		for (int i = 0; i < appWidgetIds.length; i++) {
			WidgetContainer widgetCont = findWidgetById(appWidgetIds[i]);
			if (widgetCont != null) {
				widgetContainers.remove(widgetCont);
			}
		}
	}

	/*
	 * Class-helper to collect the widget's ID, RemoteViews & his associated
	 * RateType in one place.
	 */
	static class WidgetContainer {
		private int id;
		private RemoteViews remoteViews;
		private String rateTypeId;

		WidgetContainer(int id) {
			this.id = id;
		}

		/*
		 * Setting values of views from the Rate object.
		 */
		public void setValuesFromRate(Context context, Rate rate) {
			// creating views, intent and container

			Double difference = rate.getDifference();
			Log.d(LOG_TAG, "difference " + difference);
			if (difference < 0.000001 && difference > -0.000001) {
				Log.d(LOG_TAG, difference + "");

				remoteViews = new RemoteViews(context.getPackageName(),
						R.layout.widget);
				remoteViews.setTextViewText(R.id.Change, "");
			} else if (difference > 0) {
				remoteViews = new RemoteViews(context.getPackageName(),
						R.layout.widget_up);
				remoteViews.setTextViewText(R.id.Change, "+" + difference);
			} else if (difference < 0) {
				remoteViews = new RemoteViews(context.getPackageName(),
						R.layout.widget_down);
				remoteViews.setTextViewText(R.id.Change, "" + difference);
			}

			remoteViews.setTextViewText(R.id.Name, rate.getName());
			remoteViews.setTextViewText(R.id.Value,
					Double.toString(rate.getValue()));

			DateFormat df = new SimpleDateFormat();
			remoteViews.setTextViewText(R.id.Date, df.format(rate.getDate())
					.split(" ")[0]);

			// set onClickPendingIntent
			Intent callChartsActivity = new Intent(context,
					ChartsActivity.class);
			callChartsActivity.putExtra(RATE_TYPE_ID, rateTypeId);

			PendingIntent callIntent = PendingIntent.getActivity(context, 0,
					callChartsActivity, Intent.FLAG_ACTIVITY_NEW_TASK);
			remoteViews.setOnClickPendingIntent(R.id.Widget, callIntent);

		}
	}

	/*
	 * Updating widget views with the DataProvider.
	 */
	private static void updateWidgetWithProvider(Context context,
			WidgetContainer container) {
		Log.d("updateWidgetWithProvider", "rateTypeId : "
				+ container.rateTypeId);
		if (container.rateTypeId != null) {
			ProviderManager providerManager = ProviderManager
					.getInstance(context);
			Rate rate = providerManager.getCurrentRate(container.rateTypeId);
			if (rate != null) {
				container.setValuesFromRate(context, rate);
			} else {
				RateType rateType = providerManager
						.getRateTypeByExternalId(container.rateTypeId);
				if (rateType != null) {
					String name = rateType.getSource().getCode();
					if (!rateType.getTarget().getCode().equals("")) {
						name += "/" + rateType.getTarget().getCode();
					}
					container.remoteViews.setTextViewText(R.id.Name, name);
					container.remoteViews.setTextViewText(R.id.Value,
							context.getString(R.string.unavailable));
					Date date = Calendar.getInstance().getTime();
					DateFormat df = new SimpleDateFormat();
					container.remoteViews.setTextViewText(R.id.Date,
							df.format(date).split(" ")[0]);

					Log.d(LOG_TAG, "Returned rate is Null.");
				} else {
					container.remoteViews.setTextViewText(R.id.Name, Err);
					Log.d(LOG_TAG, "Returned rateType is Null.");
				}
			}
		}
	}

	/*
	 * Finding WidgetContainer from a 'widgets' list by his ID
	 */
	private static WidgetContainer findWidgetById(int widgetId) {
		for (WidgetContainer widgetContainer : widgetContainers) {
			if (widgetContainer.id == widgetId) {
				return widgetContainer;
			}
		}
		return null;
	}

	/*
	 * update widget through WidgetManager with WidgetContainer
	 */
	private static void updateWidget(Context context, WidgetContainer container) {

		// Push update for this widget to the home screen
		AppWidgetManager manager = AppWidgetManager.getInstance(context);
		manager.updateAppWidget(container.id, container.remoteViews);
	}
}
